﻿using System;

namespace DotNetSiemensPLCToolBoxLibrary.General
{
    public static class CrcUtilities
    {
        private static ulong[] m_CrcTable = new ulong[]
		{
			0uL,
			49345uL,
			49537uL,
			320uL,
			49921uL,
			960uL,
			640uL,
			49729uL,
			50689uL,
			1728uL,
			1920uL,
			51009uL,
			1280uL,
			50625uL,
			50305uL,
			1088uL,
			52225uL,
			3264uL,
			3456uL,
			52545uL,
			3840uL,
			53185uL,
			52865uL,
			3648uL,
			2560uL,
			51905uL,
			52097uL,
			2880uL,
			51457uL,
			2496uL,
			2176uL,
			51265uL,
			55297uL,
			6336uL,
			6528uL,
			55617uL,
			6912uL,
			56257uL,
			55937uL,
			6720uL,
			7680uL,
			57025uL,
			57217uL,
			8000uL,
			56577uL,
			7616uL,
			7296uL,
			56385uL,
			5120uL,
			54465uL,
			54657uL,
			5440uL,
			55041uL,
			6080uL,
			5760uL,
			54849uL,
			53761uL,
			4800uL,
			4992uL,
			54081uL,
			4352uL,
			53697uL,
			53377uL,
			4160uL,
			61441uL,
			12480uL,
			12672uL,
			61761uL,
			13056uL,
			62401uL,
			62081uL,
			12864uL,
			13824uL,
			63169uL,
			63361uL,
			14144uL,
			62721uL,
			13760uL,
			13440uL,
			62529uL,
			15360uL,
			64705uL,
			64897uL,
			15680uL,
			65281uL,
			16320uL,
			16000uL,
			65089uL,
			64001uL,
			15040uL,
			15232uL,
			64321uL,
			14592uL,
			63937uL,
			63617uL,
			14400uL,
			10240uL,
			59585uL,
			59777uL,
			10560uL,
			60161uL,
			11200uL,
			10880uL,
			59969uL,
			60929uL,
			11968uL,
			12160uL,
			61249uL,
			11520uL,
			60865uL,
			60545uL,
			11328uL,
			58369uL,
			9408uL,
			9600uL,
			58689uL,
			9984uL,
			59329uL,
			59009uL,
			9792uL,
			8704uL,
			58049uL,
			58241uL,
			9024uL,
			57601uL,
			8640uL,
			8320uL,
			57409uL,
			40961uL,
			24768uL,
			24960uL,
			41281uL,
			25344uL,
			41921uL,
			41601uL,
			25152uL,
			26112uL,
			42689uL,
			42881uL,
			26432uL,
			42241uL,
			26048uL,
			25728uL,
			42049uL,
			27648uL,
			44225uL,
			44417uL,
			27968uL,
			44801uL,
			28608uL,
			28288uL,
			44609uL,
			43521uL,
			27328uL,
			27520uL,
			43841uL,
			26880uL,
			43457uL,
			43137uL,
			26688uL,
			30720uL,
			47297uL,
			47489uL,
			31040uL,
			47873uL,
			31680uL,
			31360uL,
			47681uL,
			48641uL,
			32448uL,
			32640uL,
			48961uL,
			32000uL,
			48577uL,
			48257uL,
			31808uL,
			46081uL,
			29888uL,
			30080uL,
			46401uL,
			30464uL,
			47041uL,
			46721uL,
			30272uL,
			29184uL,
			45761uL,
			45953uL,
			29504uL,
			45313uL,
			29120uL,
			28800uL,
			45121uL,
			20480uL,
			37057uL,
			37249uL,
			20800uL,
			37633uL,
			21440uL,
			21120uL,
			37441uL,
			38401uL,
			22208uL,
			22400uL,
			38721uL,
			21760uL,
			38337uL,
			38017uL,
			21568uL,
			39937uL,
			23744uL,
			23936uL,
			40257uL,
			24320uL,
			40897uL,
			40577uL,
			24128uL,
			23040uL,
			39617uL,
			39809uL,
			23360uL,
			39169uL,
			22976uL,
			22656uL,
			38977uL,
			34817uL,
			18624uL,
			18816uL,
			35137uL,
			19200uL,
			35777uL,
			35457uL,
			19008uL,
			19968uL,
			36545uL,
			36737uL,
			20288uL,
			36097uL,
			19904uL,
			19584uL,
			35905uL,
			17408uL,
			33985uL,
			34177uL,
			17728uL,
			34561uL,
			18368uL,
			18048uL,
			34369uL,
			33281uL,
			17088uL,
			17280uL,
			33601uL,
			16640uL,
			33217uL,
			32897uL,
			16448uL
		};

        public static ulong CalculateCrc(byte[] input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            ulong num = 0uL;
            for (int i = 0; i < input.Length; i++)
            {
                num = (num >> 8 ^ CrcUtilities.m_CrcTable[(int)checked((IntPtr)((num & 255uL) ^ unchecked((ulong)input[i])))]);
            }
            return num & 65535uL;
        }
    }
}
